

/**
 * Modification of UtilizationTest.java
 * 
 */

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;

import edu.uci.ics.jung.graph.Graph;
import edu.uci.ics.jung.graph.Vertex;
import edu.uci.ics.jung.io.GraphMLFile;

public class DataGenerator 
{

	private ArrayList<Task> tasks;
	private ArrayList<Job> jobs;
	private int lcm;
	private int numberOfCycles;
	
	public DataGenerator(String taskgraphFile, int numOfCycles, boolean initPriorities) throws IOException
	{
		 // Load the task graph from the graphml file
		this.tasks = getTasks(taskgraphFile);
		this.lcm = computeLCM(this.tasks);
		
		// if priorities have not been initialised
		if(initPriorities)
		{
			for(Task task : this.tasks)
			{
				task.setPriority(this.lcm - this.lcm / task.getPeriod());
			}
		}
		// sort tasks
		Collections.sort(tasks, new TaskComparator());
		
		this.numberOfCycles = numOfCycles;
		this.jobs = createJobs(this.numberOfCycles, this.lcm, this.tasks);
		// sorts all jobs
		Collections.sort(this.jobs, new JobComparator());
	}
	

	private static int computeLCM(ArrayList<Task> tasks)
	{
		int tmplcm = 1;
		for(Task task : tasks)
		{
			tmplcm = (task.getPeriod() * tmplcm) / computeGCD(task.getPeriod(), tmplcm);
		}
		return tmplcm;
	}

	private static int computeGCD(int a, int b)
	{
		int max = Math.max(a, b);
		int min = Math.min(a, b);
		
		if(min == 0)
		{
			return max;
		}
		
		return computeGCD(min, max % min);
	}
	
	private static ArrayList<Task> getTasks(String filename) throws IOException 
	{
		GraphMLFile gml = new GraphMLFile();
		Graph g = gml.load(filename);
		
		ArrayList<Task> tasks = new ArrayList<Task>();
		
		int taskID = 0;
		
		for (Iterator<Object> iter = g.getVertices().iterator(); iter.hasNext();) 
		{
			Vertex v = (Vertex) iter.next();

			Task task = new Task(taskID);
			task.setName(v.getUserDatum("Name").toString());
			task.setPeriod(Integer.parseInt((v.getUserDatum("Period")).toString()));
			task.setPriority(Integer.parseInt((v.getUserDatum("Priority")).toString()));
			task.setDeadline(Integer.parseInt((v.getUserDatum("Deadline")).toString()));
			task.setWcet(Integer.parseInt((v.getUserDatum("WCET")).toString()));
			task.setBcet(Integer.parseInt((v.getUserDatum("BCET")).toString()));
			
			task.setComputationTime(task.getWcet());
			
			tasks.add(task);
			
			taskID++;
		}
		
		return tasks;
	}
	
	private static ArrayList<Job> createJobs(int numberOfCycles, int lcm, ArrayList<Task> tasks)
	{
		ArrayList<Job> jobs = new ArrayList<Job>();
		
		int numOfTimeUnits = numberOfCycles * lcm;
		
		for(Task task : tasks)
		{
			for(int i = 0; i < numOfTimeUnits / task.getPeriod(); i++)
			{
				Job job = new Job();
				job.setRelease(task.getPeriod() * i);
				job.setTime((int)(Math.random() * (task.getWcet() - task.getBcet()) * 1.0) + task.getBcet());
				job.setInitTime(job.getTime());
				task.getJobs().add(job);
				job.setOwner(task);
				jobs.add(job);
			}
		}
		
		return jobs;
	}

	public ArrayList<Task> getTasks() {
		return tasks;
	}
	
	public ArrayList<Job> getAllJobs() {
		return jobs;
	}
	
	public int getLCM() {
		return lcm;
	}
	
	public int getNumberOfCycles() {
		return numberOfCycles;
	}
}
